home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
print
/
p1123mz4.zip
/
PLOT3D.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-02
|
39KB
|
938 lines
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <iostream.h>
#include "titillat.h"
#include "plot3d.h"
#ifndef TRUE
#define TRUE -1
#endif
#ifndef FALSE
#define FALSE 0
#endif
typedef struct
{
int x;
int y;
} box_rec;
plot3d::plot3d()
{
prime_array_allocated=FALSE;
plot_prepared=FALSE;
}
plot3d::~plot3d()
{
if (prime_array_allocated)
delete prime_array;
}
int plot3d::prepare_plot(
double (*f)(double,double),
double x_min,
double x_max,
double y_min,
double y_max,
int (*external_to_plot)(double,double),
int (*red)(double,double),
int x_division_count,
int y_division_count,
double rotation_in_degrees,
double tilt_in_degrees,
double light_x,
double light_y,
double light_z)
// This function prepares a plot for generation. If returns TRUE if
// and only if it is successful. If it is successful, "plot" may be called
// to actually generate the plot. Its parameters are as follow:
//
// f -- z=f(x,y), the function to be plotted. Before the plot is
// tilted or rotated, the z-axis runs from the bottom to the top of the
// display, the y-axis runs from the left to the right of the display,
// and the x-axis runs out of the display.
//
// x_min -- the minimum value of x to be plotted.
//
// x_max -- the maximum value of x to be plotted.
//
// y_min -- the minimum value of y to be plotted.
//
// y_max -- the maximum value of y to be plotted.
//
// external_to_plot -- a function that returns TRUE if and only if a
// point should be omitted from the plot.
//
// red -- a function that returns TRUE if and only if a point should
// be flagged for highlighting. A point should be so flagged only if it
// can be seen in the final plot.
//
// x_division_count -- the number of x divisions to be used in
// constructing the plot. At least two must be specified.
//
// y_division_count -- the number of y divisions to be used in
// constructing the plot. At least two must be specified.
//
// rotation_in_degrees -- rotation (degrees) about an axis parallel to
// the z-axis and through the center of the surface.
//
// tilt_in_degrees -- tilt (degrees) about an axis through the center
// of the surface and parallel to a line from the lower left hand corner of
// the display to the lower right hand corner of the display. The plot is
// tilted after it is rotated.
//
// (light_x,light_y,light_z) -- a vector pointing to the light source
// (at infinity). The light source remains fixed while the plot is rotated
// or tilted.
{
int display_ready;
prime_rec initialized_prime_rec;
int result;
int x_byte_num;
plot_prepared=FALSE;
if (prime_array_allocated)
{
delete prime_array;
prime_array_allocated=FALSE;
}
num_x_divisions=x_division_count;
num_y_divisions=y_division_count;
num_primes=(long) num_x_divisions;
num_primes*=((long) num_y_divisions);
// Number of quadrilaterals composing the plot.
initialized_prime_rec.base_z=(unsigned char) '\0';
initialized_prime_rec.color=(unsigned char) '\0';
initialized_prime_rec.x=(float) 0.0;
initialized_prime_rec.y=(float) 0.0;
initialized_prime_rec.z=(float) 0.0;
initialized_prime_rec.x_division_index=0;
initialized_prime_rec.y_division_index=0;
prime_array=new varray<prime_rec>(initialized_prime_rec,num_primes,5);
// Virtual array of quadrilaterals composing the plot.
if (prime_array_allocated=(prime_array->allocated()))
{
titillator_ptr=new titillator;
rotation=rotation_in_degrees;
tilt=tilt_in_degrees;
light.x=light_x;
light.y=light_y;
light.z=light_z;
evaluate_and_transform(f,x_min,x_max,y_min,y_max,
num_x_divisions,num_y_divisions,rotation,tilt,
external_to_plot,red);
// Compute the vertices, etc. of the quadrilaterals composing the
// plot.
shade();
// Compute the shade of gray for each quadrilateral composing the
// plot.
adjust_perspective();
// Force parallel lines running away from the viewer to converge at
// the horizon.
sort_back_to_front();
plot_prepared=TRUE;
delete titillator_ptr;
display_ready=display_initialized();
// Do whatever is necessary to prepare the display.
}
return (prime_array_allocated & display_ready);
}
void plot3d::evaluate_and_transform(
double (*f)(double,double),
double x_min,
double x_max,
double y_min,
double y_max,
int num_x_divisions,
int num_y_divisions,
double rotation,
double tilt,
int (*external_to_plot)(double,double),
int (*red)(double,double))
// Compute the vertices, etc. for each quadrilateral composing the plot.
{
double cos_rotation;
double cos_tilt;
double degrees_per_radian;
double magnitude;
prime_rec *prime;
long prime_num;
double radians;
double sin_rotation;
double sin_tilt;
double tem_x;
double tem_y;
double tem_z;
double x;
double x_delta;
int x_division_num;
double x_rotated;
double y;
double y_delta;
int y_division_num;
double z;
degrees_per_radian=45.0/atan(1.0);
radians=tilt/degrees_per_radian;
cos_tilt=cos(radians);
sin_tilt=sin(radians);
radians=rotation/degrees_per_radian;
cos_rotation=cos(radians);
sin_rotation=sin(radians);
z=f(x_min,y_min);
x_rotated=x_min*cos_rotation+y_min*sin_rotation;
y_prime_min=-x_min*sin_rotation+y_min*cos_rotation;
z_prime_min=-x_rotated*sin_tilt+z*cos_tilt;
y_prime_max=y_prime_min;
z_prime_max=z_prime_min;
x_prime_max=x_rotated*cos_tilt+z*sin_tilt;
x_delta=(double) (num_x_divisions-1);
x_delta=(x_max-x_min)/x_delta;
y_delta=(double) (num_y_divisions-1);
y_delta=(y_max-y_min)/y_delta;
x=x_min;
prime_num=(long) 0;
for (x_division_num=0; x_division_num < num_x_divisions; x_division_num++)
{
titillator_ptr->titillate();
y=y_min;
for (y_division_num=0; y_division_num < num_y_divisions;
y_division_num++)
{
z=f(x,y);
prime=prime_array->vm_ptr(prime_num);
if (external_to_plot(x,y))
prime->base_z=(unsigned char) 3;
else
if (red(x,y))
prime->base_z=(unsigned char) 2;
else
prime->base_z=(unsigned char) 1;
prime->x_division_index=x_division_num;
prime->y_division_index=y_division_num;
x_rotated=x*cos_rotation+y*sin_rotation;
tem_y=(-x*sin_rotation+y*cos_rotation);
prime->y=(float) tem_y;
tem_x=(x_rotated*cos_tilt+z*sin_tilt);
prime->x=(float) tem_x;
tem_z=(-x_rotated*sin_tilt+z*cos_tilt);
prime->z=(float) tem_z;
if (tem_x > x_prime_max)
x_prime_max=tem_x;
if (tem_y < y_prime_min)
y_prime_min=tem_y;
if (tem_y > y_prime_max)
y_prime_max=tem_y;
if (tem_z < z_prime_min)
z_prime_min=tem_z;
if (tem_z > z_prime_max)
z_prime_max=tem_z;
y+=y_delta;
prime_num++;
}
x+=x_delta;